package org.jradweb.core.orm;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.hibernate.SessionFactory;
import org.jradweb.core.utils.StringUtils;
import org.springframework.context.ApplicationContext;
/**
 * 
 *
 * Created On 2008-4-22
 * @author <a href="mailto:wagzhi@gmail.com">Paul Wang</a>
 * @version $Id: HibernateModel.java 149 2008-10-10 03:10:10Z wagzhi $
 * @param <T>
 */
public abstract class HibernateModel<T,PK> extends JModel<T,PK> {

	protected static SessionFactory sessionFactory;
	protected static ApplicationContext appCtx;
	protected static Map<Class,GenericDao> map=null;
	
	protected static GenericDao getDao(Class clazz){
		GenericDao dao=map.get(clazz);
		return dao;
	}
	/**
	 * 
	 * @param modelName "ModelName" or "package.ModelName"
	 * @return class or null
	 */
	public static Class getModelClass(String modelName){
		for(Class model:map.keySet()){
			if(model.getName().indexOf("."+modelName)>0){
				return model;
			}else if(model.getName().equals(modelName)){
				return model;
			}
		}
		return null;
	}
	
	public static void initialize(Map<Class,GenericDao> modelMap){
		map=modelMap;
	}
	
	public static <TT> List<TT> list(Class<TT> clazz) {
		GenericDao dao = getDao(clazz);
		return dao.getAll();
	}

	public static <TT, PK extends java.io.Serializable> TT get(Class<TT> clazz, PK id) {
		GenericDao<TT, PK> dao = getDao(clazz);
		return dao.findById(id);
	}
	/**
	 * if the model's value of proerptyName exists in database, return true.
	 * 
	 * @param <TT>
	 * @param <PK>
	 * @param clazz ModelClass name
	 * @param propertyName Model class PropertyName
	 * @param value Model Object Proerpty Value
	 * @return
	 */
	public static boolean isUnique(HibernateModel model,String propertyName[]) {
		
		//TODO support propertyName length >1
		Class clazz=model.getClass();
		GenericDao dao = getDao(clazz);
		BeanUtilsBean bean=BeanUtilsBean.getInstance();
		Object propertyValue;
		try {
			propertyValue = bean.getPropertyUtils().getProperty(model, propertyName[0]);
			String hql="where "+StringUtils.getClassName(clazz)+"."+propertyName[0]+" = :value";
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("value", propertyValue);
			List results=dao.getPage(1, 1,hql,params);
			if(results.size()==0){
				return true;
			}
			else if(results.size()==1){
				HibernateModel persistModel=(HibernateModel)results.get(0);
				return persistModel.getId().equals(model.getId())?true:false;
			}
			else {
				return false;
			}
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException(e);
		}	
	}
	
}
